﻿using System.Collections.Generic;
using System.Linq;
namespace NodeEditor
{
    public class RuntimePort
    {
        RuntimeValue runtimeValue;
        PortDirection direction;
        readonly Dictionary<string, List<RuntimeEdge>> dict = new Dictionary<string, List<RuntimeEdge>>();
        public RuntimeValue RuntimeValue
        {
            get => runtimeValue;
            set
            {
                if(direction == PortDirection.Output)
                {
                    runtimeValue = value;
                }
            }
        }

        public List<RuntimeEdge> this[string key]
        {
            get
            {
                List<RuntimeEdge> list;
                dict.TryGetValue(key, out list);
                return list;
            }
        }

        public RuntimePort(AbstractNode node,PortDirection direction)
        {
            this.direction = direction;
            if(direction == PortDirection.Input)
            {
                runtimeValue = new RuntimeValue();
            }
            foreach (var port in node.ports)
            {
                if (port.direction == direction)
                {
                    this.dict.Add(port.name, new List<RuntimeEdge>());
                }
            }
        }

        public bool IsConnect(string key)
        {
            List<RuntimeEdge> list;
            dict.TryGetValue(key, out list);
            return list?.Count > 0;
        }

        public void Connect(string key, RuntimeEdge edge)
        {
            List<RuntimeEdge> list;
            dict.TryGetValue(key, out list);
            list?.Add(edge);
        }

        public void DisConnect(string key, RuntimeEdge edge)
        {
            List<RuntimeEdge> list;
            dict.TryGetValue(key, out list);
            list?.Remove(edge);
        }

        public RuntimeNode [] GetAllNodes()
        {
            List<RuntimeNode> result = new List<RuntimeNode>();
            foreach (var list in dict.Values)
            {
                foreach(var _ in list)
                {
                    if (direction == PortDirection.Input)
                        result.Add(_.ouput);
                    else
                        result.Add(_.input);
                }
            }
            return result.ToArray();
        }

        public RuntimeNode[] GetConnectNodes(string key)
        {
            List<RuntimeEdge> result;
            dict.TryGetValue(key, out result);
            return result?.Select(p => direction == PortDirection.Input ? p.ouput : p.input).ToArray();
        }

        public bool Contains(string key)
        {
            return dict.ContainsKey(key);
        }

        public bool ContainsConnect(RuntimeNode node)
        {
            foreach (var list in dict.Values)
            {
                foreach (var _ in list)
                {
                    if (_.ouput == node || _.input == node)
                        return true;
                }
            }
            return false;
        }

        public void Clear()
        {
            var array = dict.Values;
            foreach (var list in dict.Values)
            {
                while (list.Count>0)
                {
                    list[0].DisConnect();
                }
            }
        }
    }
}